home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2000 #5 / Amiga Plus CD - 2000 - No. 5.iso / Tools / Dev / FPSE_src / cdrom.c < prev    next >
C/C++ Source or Header  |  2000-01-01  |  23KB  |  882 lines

  1. /*
  2.         cdrom.c by BERO
  3.         modified by LDChen
  4.         info from psx.rules.org / doomed@c64.org
  5. */
  6.  
  7. #include "fpse.h"
  8.  
  9. #define   RAMADDR(addr)     ((void*)&ram[(addr)&0x1fffff])
  10.  
  11. #define CACHE_ENABLE      1
  12. #define CACHE_SIZE        256
  13. #define CACHE_PRE_READ    16
  14. #define CACHE_SLOT_SIZE   (2048+512)    // easy calculation
  15.  
  16. #define   INT2BCD(a)        ((a/10)*16+(a%10))
  17. #define   BCD2INT(a)        ((a>>4)*10+(a&0xf))
  18.  
  19. #define CON_OUTPUT        0
  20.  
  21. enum {
  22.     CdlSync,    CdlNop,       CdlSetloc,  CdlPlay,      // 00-03 ; 00-03
  23.     CdlForward, CdlBackword,  CdlReadN,   CdlStandby,   // 04-07 ; 04-07
  24.     CdlStop,    CdlPause,     CdlInit,    CdlMute,      // 08-11 ; 08-0B
  25.     CdlDemute,  CdlSetfilter, CdlSetmode, CdlGetparam,  // 12-15 ; 0C-0F
  26.     CdlGetlocL, CdlGetlocP,   Cdl18,      CdlGetTN,     // 16-19 ; 10-13
  27.     CdlGetTD,   CdlSeekL,     CdlSeekP,   Cdl23,        // 20-23 ; 14-17
  28.     Cdl24,      CdlTest,      CdlCheckID, CdlReadS,     // 24-27 ; 18-1B
  29.     CdlReset,   Cdl29,        CdlReadTOC                // 28-30 ; 1C-1E
  30. };
  31.  
  32. enum {
  33.     ModeSpeed = 0x80,        /* 0: normal speed  1: double speed */
  34.     ModeRT    = 0x40,        /* 0: ADPCM off     1: ADPCM on     */
  35.     ModeSize1 = 0x20,        /* 0: 2048 byte     1: 2340 byte    */
  36.     ModeSize0 = 0x10,        /* 0: -             1: 2328 byte    */
  37.     ModeSF    = 0x08,        /* 0: Channel off   1: Channel on   */
  38.     ModeRept  = 0x04,        /* 0: Report off    1: Report on    */
  39.     ModeAP    = 0x02,        /* 0: AutoPause off 1: AutoPause on */
  40.     ModeDA    = 0x01         /* 0: CD-DA off     1: CD-DA on     */
  41. };
  42.  
  43. enum {
  44.     StatPlay      = 0x80,        /* playing CD-DA */
  45.     StatSeek      = 0x40,        /* seeking */
  46.     StatRead      = 0x20,        /* reading data frames */
  47.     StatShellOpen = 0x10,        /* once shell open */
  48.     StatSeekError = 0x04,        /* seek error detected */
  49.     StatStandby   = 0x02,        /* spindle motor rotating */
  50.     StatError     = 0x01         /* command error detected */
  51. };
  52.  
  53. enum {
  54.     NoIntr      = 0x00,        /* No interrupt */
  55.     DataReady   = 0x01,        /* Data Ready */
  56.     Acknowledge = 0x02,        /* Acknowledge */
  57.     Complete    = 0x03,        /* Command Complete */
  58.     DataEnd     = 0x04,        /* End of Data Detected */
  59.     DiskError   = 0x05         /* Error Detected */
  60. };
  61.  
  62. typedef struct {
  63.     UINT8 minute;
  64.     UINT8 second;
  65.     UINT8 frame;
  66.     UINT8 pad;
  67. } CDLoc;
  68.  
  69. static struct {
  70. // Registers
  71.     UINT8 stat;
  72.     UINT8 ctrl;
  73.     UINT8 mode;
  74.     UINT8 Status;
  75.  
  76. // Param
  77.     UINT8   param[8];
  78.     int     paramptr;
  79.  
  80. // Result
  81.     UINT8 result[8];
  82.     int   resultptr;
  83.     int   resultsize;
  84.     int   resultready;
  85.  
  86. // CDR Locations
  87.     CDLoc   Loc;
  88.     CDLoc   SeekLoc;
  89.  
  90. // Async Related
  91.     UINT8   NextStat;
  92.     UINT8   DmaReady;
  93.     UINT8   Reset;
  94.     UINT8   AsyncCause;
  95.     UINT32  NextSize;
  96.     UINT8   NextParam[8];
  97.  
  98. // Buffers
  99.     UINT8  *SectorBuf;
  100.     UINT32  SectorSize;
  101.     UINT8   LastReadInfo[8];
  102.  
  103.     UINT8       file;
  104.     UINT8       chan;
  105.     UINT8       moderead;
  106.     UINT8       storedmoderead;
  107.     int         retries;
  108. } cd;
  109.  
  110. #ifdef MSB_FIRST
  111. #define MAKEID(a,b,c,d) ( d + (c << 8) + (b << 16) + (a << 24) )
  112. #else
  113. #define MAKEID(a,b,c,d) ( a + (b << 8) + (c << 16) + (d << 24) )
  114. #endif
  115.  
  116. // PSX_COUNTRY == USE_EUROPE_PSX
  117. static UINT8 EU_Cmd25P22[8]={ 0x66,0x6F,0x72,0x20,0x55,0x2F,0x43,0x00 }; // "for U/C"
  118. static UINT8 EU_Cmd25P23[8]={ 0x43,0x58,0x44,0x32,0x35,0x34,0x35,0x51 }; // "CXD2545Q"
  119. static UINT8 EU_Cmd25P24[8]={ 0x43,0x58,0x44,0x32,0x35,0x34,0x35,0x51 }; // "CXD2545Q"
  120. static UINT8 EU_Cmd25P25[8]={ 0x43,0x58,0x44,0x31,0x38,0x31,0x35,0x51 }; // "CXD1815Q"
  121. static UINT8 EU_SCEx[6] = { 0x09, 0xA9, 0x3D, 0x2B, 0xA5, 0x74 };  // SCEE European
  122. static UINT32 EU_SCExID = MAKEID('S','C','E','E');
  123.  
  124. // PSX_COUNTRY == USE_AMERICAN_PSX
  125. static UINT8 US_Cmd25P22[8]={ 0x66,0x6F,0x72,0x20,0x55,0x53,0x2F,0x41 }; // "for US/A"
  126. static UINT8 US_Cmd25P23[8]={ 0x43,0x58,0x44,0x31,0x37,0x38,0x32,0x42 }; // "CXD1782B"
  127. static UINT8 US_Cmd25P24[8]={ 0x43,0x58,0x44,0x32,0x35,0x31,0x36,0x51 }; // "CXD2516Q"
  128. static UINT8 US_Cmd25P25[8]={ 0x43,0x58,0x44,0x31,0x31,0x39,0x39,0x42 }; // "CXD1199B"
  129. static UINT8 US_SCEx[6] = { 0x09, 0xA9, 0x3D, 0x2B, 0xA5, 0xF4 };  // SCEA U.S.
  130. static UINT32 US_SCExID = MAKEID('S','C','E','A');
  131.  
  132. // PSX_COUNTRY == USE_JAPAN_PSX
  133. static UINT8 JP_Cmd25P22[8]={ 0x66,0x6F,0x72,0x20,0x4A,0x61,0x70,0x61 }; // "for Japa"
  134. static UINT8 JP_Cmd25P23[8]={ 0x43,0x58,0x44,0x32,0x35,0x34,0x35,0x51 }; // "CXD2545Q"
  135. static UINT8 JP_Cmd25P24[8]={ 0x43,0x58,0x44,0x32,0x35,0x34,0x35,0x51 }; // "CXD2545Q"
  136. static UINT8 JP_Cmd25P25[8]={ 0x43,0x58,0x44,0x31,0x38,0x31,0x35,0x51 }; // "CXD1815Q"
  137. static UINT8 JP_SCEx[6] = { 0x09, 0xA9, 0x3D, 0x2B, 0xA5, 0x74 };  // SCEI Japanese
  138. static UINT32 JP_SCExID = MAKEID('S','C','E','I');
  139.  
  140. static UINT8 Cmd25P22[8];
  141. static UINT8 Cmd25P23[8];
  142. static UINT8 Cmd25P24[8];
  143. static UINT8 Cmd25P25[8];
  144. static UINT8 SCEx[6];
  145. static UINT32 SCExID;
  146.  
  147. #if CACHE_ENABLE==0
  148. static UINT8 SectorBuf[CACHE_SLOT_SIZE];
  149. #else
  150. static UINT8 SectorBuf[CACHE_SLOT_SIZE*CACHE_SIZE];
  151. static CDLoc CacheAddress[CACHE_SIZE];
  152. static int   CacheIdx = 0;
  153.  
  154. static void init_cd_cache(void)
  155. {
  156.     memset(CacheAddress,0,CACHE_SIZE*sizeof(CDLoc));
  157. }
  158.  
  159. static UINT8 *get_cd_cache(CDLoc *loc)
  160. {
  161.     int   x;
  162.     UINT8 *sect,*ret;
  163.     CDLoc l;
  164.  
  165. // Search in the cache
  166.     for (x=0; x<CACHE_SIZE; x++)
  167.         if (*(UINT32 *)loc == *(UINT32 *)(CacheAddress+x))
  168.             return &SectorBuf[x*CACHE_SLOT_SIZE];
  169.  
  170. // Save position for return
  171.     ret = &SectorBuf[CacheIdx*CACHE_SLOT_SIZE];
  172.     l = *loc;
  173. // Read 'CACHE_PRE_READ' sectors per time instead of one (more speed)
  174.     for (x=0; x<CACHE_PRE_READ; x++)
  175.     {
  176.         CacheAddress[CacheIdx] = l;                   // Set active address
  177.         sect = CD_Read((UINT8 *)&l);                  // read the sector
  178.         CD_Wait();                                    // wait end-of-read
  179.         memcpy(&SectorBuf[CacheIdx*CACHE_SLOT_SIZE],
  180.                                          sect,2352);  // copy sector in cache
  181.  
  182.         if (++l.frame >= 75)                          // Advance CD pointer
  183.         {
  184.             l.frame = 0;
  185.             if (++l.second >= 60) 
  186.             {
  187.                 l.second=0;
  188.                 l.minute++;
  189.             }
  190.         }
  191.  
  192.         if (++CacheIdx >= CACHE_SIZE) CacheIdx = 0;   // Go to next slot
  193.     }
  194.  
  195.     return ret;
  196. }
  197. #endif
  198.  
  199. #define EVENT_SETUP(n,irq,s)  VSync_Register |= 0x80000000 | (1<<INT_CD); \
  200.                               Event_List[INT_CD] = n;    \
  201.                               cd.NextStat = irq; cd.NextSize = s
  202.  
  203. /*
  204.     result[0]
  205.  
  206.     0x80 CD-DA Play
  207.     0x02 working?
  208. */
  209.  
  210. static int get_sector_size()
  211. {
  212.     switch( cd.mode & 0x30 ) {
  213.     case 0x00: return 2048;
  214.     case 0x10: return 2328;
  215.     case 0x20: return 2352;
  216.     }
  217.     return 2352;
  218. }
  219.  
  220. static int UpdateSeekPosition()
  221. {
  222. /*
  223.     if ((cd.mode & ModeRept) &&
  224.         (cd.Status & StatPlay))
  225.     {
  226.         CD_GetSeek((UINT8*)&cd.SeekLoc);
  227.         return 1;
  228.     }
  229. */
  230.     if (++cd.SeekLoc.frame >= 75)
  231.     {
  232.         cd.SeekLoc.frame = 0;
  233.         if (++cd.SeekLoc.second >= 60) 
  234.         {
  235.             cd.SeekLoc.second=0;
  236.             cd.SeekLoc.minute++;
  237.         }
  238.     }
  239.     return 0;
  240. }
  241.  
  242. #if CON_OUTPUT
  243. static int cnt = 0;
  244. #endif
  245.  
  246. static int cdrom_async()
  247. {
  248. #if CON_OUTPUT
  249.     printf("ASync=%d - ctrl=%x\n",cd.AsyncCause,cd.ctrl);
  250. #endif
  251.  
  252. /*
  253.     if (cd.ctrl & 0x40)
  254.     {
  255.         if (cnt<10)
  256.         {
  257.             PRINTF("Forward CDIRQ\n");
  258.             cnt++;
  259.             VSync_Register |= 0x80000000 | (1<<INT_CD);
  260.             Event_List[INT_CD] = 100;
  261.             return;
  262.         }
  263.         cnt = 0;
  264.         cd.ctrl &= ~0x40;
  265.     }
  266. */
  267.     if (hwarea[0x1070] && (1<<INT_CD)) // cd.stat == 1)
  268.     {
  269.         if (cd.retries<10)
  270.         {
  271. //if (cd.NextStat != 3) {
  272. #if CON_OUTPUT
  273.             PRINTF("%3d) Forward CDIRQ\n",cnt);
  274.             cnt++;
  275. #endif
  276. //}
  277.             cd.retries++;
  278.             VSync_Register |= 0x80000000 | (1<<INT_CD);
  279.             Event_List[INT_CD] = 50;
  280.             return 0;
  281.         }
  282.     }
  283.     cd.retries = 0;
  284.  
  285. //cnt = 0;
  286. #if CON_OUTPUT
  287.     printf("Setup CDIRQ %d\n",cd.NextStat);
  288. #endif
  289.  
  290.     if (CD_Wait() != FPSE_OK)
  291.     {
  292. #if CON_OUTPUT
  293.         printf("CDIRQ error detected\n");
  294. #endif
  295.         cd.NextParam[0] |= StatError;
  296.         cd.NextStat = DiskError;
  297.         cd.NextSize = 1;
  298.         cd.DmaReady = 0;
  299.     }
  300.  
  301.     cd.stat         = cd.NextStat;
  302.     cd.resultsize   = cd.NextSize;
  303.     cd.resultptr    = 0;
  304.     cd.resultready  = 1;
  305.     cd.ctrl        &= ~(0x80|0x40);
  306.     cd.ctrl        |= cd.DmaReady;
  307.     cd.DmaReady = 0;
  308.     memcpy(cd.result,cd.NextParam,8);
  309.  
  310.     if (cd.stat == DiskError) return 1;
  311.  
  312.     switch (cd.AsyncCause) {
  313.     case 1: // Read
  314. #if CACHE_ENABLE==1
  315.         if (cdusecache) cd.SectorBuf  = get_cd_cache(&cd.SeekLoc);
  316.                    else
  317. #endif
  318.         cd.SectorBuf  = CD_Read((UINT8 *)&cd.SeekLoc);
  319.  
  320.         cd.SectorSize = get_sector_size();
  321.         cd.NextParam[0] = cd.Status;
  322.         cd.AsyncCause = 5;
  323.         cd.DmaReady = 0x40;
  324.         EVENT_SETUP(100,1,1);
  325.         break;
  326.     case 2: // Pause
  327.         cd.AsyncCause   = 0;
  328.         cd.NextParam[0] = cd.Status;
  329.         cd.ctrl |= 0x80; // (cd.ctrl | 0x80) & ~0x40;
  330.         EVENT_SETUP(100,2,1);
  331.         break;
  332.     case 3: // Play
  333.         cd.SectorSize = get_sector_size();
  334.         cd.AsyncCause = 4;
  335.         cd.NextParam[0] = 0;
  336.         UpdateSeekPosition();
  337.         EVENT_SETUP(400,3,1);
  338.         break;
  339.     case 4:
  340.         cd.AsyncCause = 3;
  341.  
  342.         cd.NextParam[0] = cd.Status;
  343.         if (cd.mode & ModeRept)
  344.         {
  345.             cd.NextParam[1] = 1;
  346.             cd.NextParam[2] = 0x80;
  347.             cd.NextParam[3] = INT2BCD(cd.SeekLoc.minute);
  348.             cd.NextParam[4] = INT2BCD(cd.SeekLoc.second) | 0x80;
  349.             cd.NextParam[5] = INT2BCD(cd.SeekLoc.frame);
  350.             EVENT_SETUP(400,1,8);
  351.         } else EVENT_SETUP(400,1,1);
  352.         break;
  353.     case 5:
  354.         if (cd.SectorBuf != NULL) {
  355.             memcpy(SectorBuf,cd.SectorBuf,2352);
  356.             memcpy(cd.LastReadInfo,cd.SectorBuf,8);
  357.         }
  358.         cd.SectorBuf = SectorBuf;
  359.         UpdateSeekPosition();
  360.         switch ((cd.moderead = cd.storedmoderead)) {
  361.         case 0:
  362.             cd.SectorBuf += 12; break;
  363.         }
  364.         cd.AsyncCause = 1;
  365.  
  366.         cd.NextParam[0] = cd.Status | StatRead;
  367.         EVENT_SETUP(100,3,1);
  368.         break;
  369.     case 6: // CdlSync
  370.         cd.AsyncCause   = 2;
  371.         cd.NextParam[0] = cd.Status;
  372.         cd.ctrl |= 0x80;
  373.         EVENT_SETUP(100,4,1);
  374.         break;
  375.  
  376.     case 7: // ReadS
  377. #if CACHE_ENABLE==1
  378.         if (cdusecache) cd.SectorBuf  = get_cd_cache(&cd.SeekLoc);
  379.                    else
  380. #endif
  381.         cd.SectorBuf  = CD_Read((UINT8 *)&cd.SeekLoc);
  382.  
  383.         cd.SectorSize = get_sector_size();
  384.         cd.NextParam[0] = cd.Status;
  385.         cd.AsyncCause = 8;
  386.         cd.DmaReady = 0x40;
  387.         EVENT_SETUP(140,1,1);
  388.         break;
  389.  
  390.     case 8:
  391.         if (cd.SectorBuf != NULL) {
  392.             memcpy(SectorBuf,cd.SectorBuf,2352);
  393.             memcpy(cd.LastReadInfo,cd.SectorBuf,8);
  394.         }
  395.         cd.SectorBuf = SectorBuf;
  396.         UpdateSeekPosition();
  397.         switch ((cd.moderead = cd.storedmoderead)) {
  398.         case 0:
  399.             cd.SectorBuf += 12; break;
  400.         }
  401.         cd.AsyncCause = 7;
  402.  
  403.         cd.NextParam[0] = cd.Status | StatRead;
  404.         EVENT_SETUP(25,3,1);
  405.         break;
  406.  
  407.     default:
  408.         cd.AsyncCause = 0;
  409.         break;
  410.     }
  411.  
  412.     return 1;
  413. }
  414.  
  415. void cd_initvar()
  416. {
  417.     memset(&cd,0,sizeof(cd));
  418.     VSyncCallBack[INT_CD] = cdrom_async;
  419. #if CACHE_ENABLE==1
  420.     init_cd_cache();
  421. #endif
  422.  
  423.     switch (psx_country)
  424.     {
  425.     case USE_AMERICAN_PSX:
  426.         memcpy(Cmd25P22,US_Cmd25P22,sizeof(Cmd25P22));
  427.         memcpy(Cmd25P23,US_Cmd25P23,sizeof(Cmd25P23));
  428.         memcpy(Cmd25P24,US_Cmd25P24,sizeof(Cmd25P24));
  429.         memcpy(Cmd25P25,US_Cmd25P25,sizeof(Cmd25P25));
  430.         memcpy(SCEx,US_SCEx,sizeof(SCEx));
  431.         SCExID = US_SCExID;
  432.         printf("SCEA zone selected.\n");
  433.         break;
  434.     case USE_EUROPE_PSX:
  435.         memcpy(Cmd25P22,EU_Cmd25P22,sizeof(Cmd25P22));
  436.         memcpy(Cmd25P23,EU_Cmd25P23,sizeof(Cmd25P23));
  437.         memcpy(Cmd25P24,EU_Cmd25P24,sizeof(Cmd25P24));
  438.         memcpy(Cmd25P25,EU_Cmd25P25,sizeof(Cmd25P25));
  439.         memcpy(SCEx,EU_SCEx,sizeof(SCEx));
  440.         SCExID = EU_SCExID;
  441.         printf("SCEE zone selected.\n");
  442.         break;
  443.     case USE_JAPAN_PSX:
  444.         memcpy(Cmd25P22,JP_Cmd25P22,sizeof(Cmd25P22));
  445.         memcpy(Cmd25P23,JP_Cmd25P23,sizeof(Cmd25P23));
  446.         memcpy(Cmd25P24,JP_Cmd25P24,sizeof(Cmd25P24));
  447.         memcpy(Cmd25P25,JP_Cmd25P25,sizeof(Cmd25P25));
  448.         memcpy(SCEx,JP_SCEx,sizeof(SCEx));
  449.         SCExID = JP_SCExID;
  450.         printf("SCEI zone selected.\n");
  451.         break;
  452.     }
  453. }
  454.  
  455. int cd0_read(void)
  456. {
  457.     int ret = cd.ctrl;
  458.     if (cd.resultsize && cd.resultready) ret|=0x20; else ret&=~0x20;
  459. //    printf("read cd0 %x\n",ret|0x18);
  460.     return ret|0x18;
  461. }
  462.  
  463. int cd1_read(void)
  464. {
  465.     int ret=0;
  466.  
  467.     if (cd.resultsize) {
  468.         ret = cd.result[cd.resultptr++];
  469.         if (cd.resultptr>=cd.resultsize) {
  470.             cd.resultptr = cd.resultsize = 0;
  471.             cd.resultready = 0;
  472.         }
  473.     }
  474.  
  475. //    printf("read cd1 %x\n",ret);
  476.     return ret;
  477. }
  478.  
  479. int cd2_read(void)
  480. {
  481. //        printf("read cd2 ,0\n");
  482.     return 0;
  483. }
  484.  
  485. int cd3_read(void)
  486. {
  487. //    printf("read cd3 %x\n",cd.stat);
  488.  
  489.     return cd.stat;
  490. }
  491.  
  492. #define   RESULT(n)       cd.result[0] = n; cd.resultsize = 1
  493. #define   SRESULT         cd.result[0] = cd.Status; cd.resultsize = 1
  494.  
  495. void cd0_write(int data)
  496. {
  497. /*   write 0??
  498.      write read & 3?
  499. */
  500. //  printf("write cd0 %x\n",data);
  501. //  cd.ctrl = data;
  502.     if (data==0) {
  503.         cd.paramptr = 0;
  504.         cd.resultready = 0;
  505.     }
  506.     if (data&1) cd.resultready = 1;
  507.     if (data==1) cd.Reset = 1;
  508. }
  509.  
  510. void cd2_write(int data)
  511. {
  512. //  printf("write cd2 %x\n",data);
  513.     if (cd.Reset==2 && data==7) {
  514.         cd.paramptr = 0;
  515.         cd.resultready = 1;
  516.         cd.Reset = 0;
  517.         cd.stat = 0;
  518.         cd.ctrl = cd.ctrl & ~3; // 0;
  519.         return;
  520.     }
  521.     cd.Reset = 0;
  522.     if (cd.paramptr<8)
  523.         cd.param[cd.paramptr++] = data;
  524. }
  525.  
  526. void cd3_write(int data)
  527. {
  528. //  cd.stat = data;
  529. //  printf("write cd3 %x\n",data);
  530.     if (data==7 && cd.Reset==1) cd.Reset=2;
  531.                            else cd.Reset=0;
  532.     if (cd.resultready && data==7) {
  533.         cd.resultsize = cd.resultptr = 0;
  534.         cd.stat = 0;
  535.     }
  536. }
  537.  
  538. #if CON_OUTPUT
  539. #define PRINTRESULT \
  540.     printf(" Resultsize=%2d - %02x %02x %02x %02x %02x %02x %02x %02x\n", \
  541.            cd.resultsize,                                                 \
  542.            cd.result[0], cd.result[1], cd.result[2], cd.result[3],        \
  543.            cd.result[4], cd.result[5], cd.result[6], cd.result[7]);
  544. #else
  545. #define PRINTRESULT
  546. #endif
  547.  
  548. void cd1_write(int data)
  549. {
  550.     static char *cmdname[]= {
  551.     "CdlSync",    "CdlNop",       "CdlSetloc",  "CdlPlay",
  552.     "CdlForward", "CdlBackword",  "CdlReadN",   "CdlStandby",
  553.     "CdlStop",    "CdlPause",     "CdlReset",   "CdlMute",
  554.     "CdlDemute",  "CdlSetfilter", "CdlSetmode", "CdlGetparam",
  555.     "CdlGetlocL", "CdlGetlocP",   "Cdl18",      "CdlGetTN",
  556.     "CdlGetTD",   "CdlSeekL",     "CdlSeekP",   "Cdl23",
  557.     "Cdl24",      "CdlTest",      "CdlCheckID", "CdlReadS"
  558.     };
  559.  
  560.     if (data<28) {
  561.         PRINTF("%s\n",cmdname[data]);
  562.     }
  563.  
  564. #if CON_OUTPUT
  565.     printf("Command %x - Code %02x %02x %02x %02x %02x %02x %02x %02x\n",
  566.            data,
  567.            cd.param[0], cd.param[1], cd.param[2], cd.param[3],
  568.            cd.param[4], cd.param[5], cd.param[6], cd.param[7]);
  569. #endif
  570.  
  571.     cd.stat = 2;
  572.     switch(data){
  573.     case CdlSync:
  574.         cd.NextParam[0] = cd.Status;
  575.         cd.AsyncCause = 6;
  576.         EVENT_SETUP(100,3,1);
  577.         cd.ctrl |= 0x80;
  578.         cd.stat = 3;
  579.         PRINTRESULT
  580.         return;
  581.  
  582.     case CdlNop:
  583.         cd.stat = 3;
  584.         SRESULT;
  585.         break;
  586.  
  587.     case CdlSetloc:
  588.         if (!(cd.param[0] | cd.param[1] | cd.param[2]))
  589.         {
  590.             cd.Loc = cd.SeekLoc;
  591.         } else {
  592.             cd.Loc.minute = BCD2INT(cd.param[0]);
  593.             cd.Loc.second = BCD2INT(cd.param[1]);
  594.             cd.Loc.frame  = BCD2INT(cd.param[2]);
  595.         }
  596.         cd.Status |= StatStandby;
  597.         cd.NextParam[0] = cd.Status;
  598.         cd.AsyncCause = 0;
  599.         EVENT_SETUP(100,3,1);
  600.         cd.ctrl |= 0x80;
  601.         PRINTRESULT
  602.         return;
  603. /*
  604.         SRESULT;
  605.         break;
  606. */
  607.     case CdlPlay:
  608.         CD_Play((UINT8 *)&cd.SeekLoc);
  609.         cd.Status |= (StatPlay | StatStandby);
  610.         cd.NextParam[0] = cd.Status;
  611.         cd.AsyncCause = 4;
  612.         EVENT_SETUP(400,3,1);
  613.         cd.DmaReady = 0x40;
  614.         cd.ctrl |= 0x80;
  615.         PRINTRESULT
  616.         return;
  617.  
  618.     case CdlForward:
  619.     case CdlBackword:
  620.         cd.stat = 2;
  621.         SRESULT;
  622.         break;
  623.  
  624.     case CdlReadS:
  625.         cd.AsyncCause = 7;
  626.         goto ContinueRead;
  627.     case CdlReadN:
  628.         cd.AsyncCause = 1;
  629. ContinueRead:
  630.         cd.Status |= StatStandby;
  631.         if (memcmp(&cd.SeekLoc,&cd.Loc,sizeof(CDLoc)))
  632.             cd.SeekLoc = cd.Loc;
  633.         cd.NextParam[0] = cd.Status;
  634.         EVENT_SETUP(100,3,1);
  635. //        cd.SectorBuf  = cd_read((UINT8 *)&cd.SeekLoc);
  636. //        cd.SectorSize = get_sector_size();
  637.         cd.ctrl |= 0x80;
  638.         PRINTRESULT
  639.         return;
  640.  
  641.     case CdlInit:
  642.         cd.mode = 0;
  643.     case CdlReset:
  644.     case CdlStandby:
  645.         cd.stat = 2;
  646.         cd.Status = (cd.Status & ~StatPlay) | StatStandby;
  647.         SRESULT;
  648.         break;
  649.  
  650.     case CdlStop:
  651.         cd.stat = 2;
  652.         if (cd.Status & StatPlay)
  653.             CD_Stop();
  654.         cd.Status &= ~(StatPlay | StatStandby);
  655.         SRESULT;
  656.         break;
  657.  
  658.     case CdlPause:
  659. //        if (++cnt>=17) FPSE_Flags |= VERBOSE | DISASMFLG;
  660.  
  661.         if (cd.Status & StatPlay) CD_Stop();
  662.         cd.Status = (cd.Status & ~StatPlay) | StatStandby;
  663.         cd.AsyncCause = 2;
  664.         cd.NextParam[0] = cd.Status;
  665. //        cd.stat = 4;
  666.         EVENT_SETUP(10,4,1); // 4,2,1);
  667.         cd.DmaReady = 0x40;
  668.         cd.ctrl |= 0x80; // (cd.ctrl | 0x80) & ~0x40;
  669.         PRINTRESULT
  670.         return;
  671.  
  672.     case CdlMute:
  673.     case CdlDemute:
  674.         cd.stat = 2;
  675.         SRESULT;
  676.         break;
  677.  
  678.     case CdlSetfilter:
  679.         cd.stat = 2;
  680.         cd.file = cd.param[0];
  681.         cd.chan = cd.param[1];
  682.         SRESULT;
  683.         break;
  684.  
  685.     case CdlSetmode:
  686.         cd.mode = cd.param[0];
  687.         cd.storedmoderead = (cd.mode & 0x30) >> 4;
  688.         cd.Status |= StatStandby;
  689.         cd.NextParam[0] = cd.Status;
  690.         cd.AsyncCause = 0;
  691.         EVENT_SETUP(100,3,1);
  692.         cd.ctrl |= 0x80;
  693.         PRINTRESULT
  694.         return;
  695.  
  696.         SRESULT;
  697.         break;
  698.  
  699.     case CdlGetparam:
  700.         cd.stat = 2;
  701.         cd.result[0] = cd.Status; /* status */
  702.         cd.result[1] = cd.mode;
  703.         cd.result[2] = cd.file; /* file */
  704.         cd.result[3] = cd.chan; /* channel */
  705.         cd.result[4] = 0;
  706.         cd.result[5] = 0;
  707.         cd.resultsize = 6;
  708.         break;
  709.  
  710.     case CdlGetlocL:
  711.         cd.stat = 2;
  712. /*
  713.         cd.result[0] = INT2BCD(cd.SeekLoc.minute); // min
  714.         cd.result[1] = INT2BCD(cd.SeekLoc.second); // sec
  715.         cd.result[2] = INT2BCD(cd.SeekLoc.frame);  // frame
  716.         cd.result[3] = cd.mode; // mode
  717.         cd.result[4] = cd.file; // file
  718.         cd.result[5] = cd.chan; // channel
  719.         cd.resultsize = 6;
  720. */
  721.         memcpy(cd.result,cd.LastReadInfo,8);
  722.         cd.resultsize = 8;
  723.         break;
  724.  
  725.     case CdlGetlocP:
  726.         cd.stat = 2;
  727.         cd.result[0] = 1; /* track */
  728.         cd.result[1] = 0; /* index */
  729.         cd.result[2] = cd.LastReadInfo[0]; /* min  */
  730.         cd.result[3] = cd.LastReadInfo[1]; /* sec */
  731.         cd.result[4] = cd.LastReadInfo[2]; /* frame */
  732.         cd.result[5] = cd.LastReadInfo[0]; /* Amin  */
  733.         cd.result[6] = cd.LastReadInfo[1]; /* Asec */
  734.         cd.result[7] = cd.LastReadInfo[2]; /* Aframe */
  735.         cd.resultsize = 8;
  736.         break;
  737.  
  738.     case CdlGetTN:
  739.         cd.stat = 2;
  740.         CD_GetTN(cd.result);
  741.         cd.result[0] = cd.Status; /* status */
  742.         cd.result[1] = INT2BCD(cd.result[1]); /* first track */
  743.         cd.result[2] = INT2BCD(cd.result[2]); /* total track */
  744.         cd.resultsize = 3;
  745.         break;
  746.  
  747.     case CdlGetTD:
  748.         cd.stat = 2;
  749.         CD_GetTD(cd.result,cd.param[0]);
  750.         cd.result[0] = cd.Status; /* status */
  751.         cd.result[1] = INT2BCD(cd.result[1]); /* min */
  752.         cd.result[2] = INT2BCD(cd.result[2]); /* sec */
  753.         cd.resultsize = 3;
  754.         break;
  755.  
  756.     case CdlSeekL:
  757.     case CdlSeekP:
  758.         cd.SeekLoc = cd.Loc;
  759. #if CON_OUTPUT
  760.         printf("%02x:%02x:%02x\n",
  761.                 cd.SeekLoc.minute,cd.SeekLoc.second,cd.SeekLoc.frame);
  762. #endif
  763.         cd.Status |= StatStandby;
  764.         cd.NextParam[0] = cd.Status;
  765.         cd.AsyncCause = 0;
  766.         EVENT_SETUP(100,2,1);
  767.         cd.ctrl |= 0x80;
  768.         PRINTRESULT
  769.         return;
  770.  
  771.         cd.Status |= StatStandby;
  772.         SRESULT;
  773.         break;
  774.  
  775.     case CdlTest:
  776.         cd.Status |= StatStandby;
  777.         switch (cd.param[0]) {
  778.         case 0x20:
  779.             cd.result[0] = 0x94;    // BIOS Timestamps
  780.             cd.result[1] = 0x09;
  781.             cd.result[2] = 0x19;
  782.             cd.result[3] = 0xC0;
  783.             break;
  784.         case 0x22:
  785.             memcpy(cd.result,Cmd25P22,8);
  786.             break;
  787.         case 0x23:
  788.             memcpy(cd.result,Cmd25P23,8);
  789.             break;
  790.         case 0x24:
  791.             memcpy(cd.result,Cmd25P24,8);
  792.             break;
  793.         case 0x25:
  794.             memcpy(cd.result,Cmd25P25,8);
  795.             break;
  796.         }
  797.         cd.resultsize = 8;
  798.         cd.stat = 3;
  799.         break;
  800.  
  801.     case CdlCheckID:
  802.         cd.result[0] = 0x08;  // 0x10=Audio CD    0x08=Data Tracks
  803.                               // 0x00=Don't Known
  804.         cd.result[1] = 0x00;  // 0x80=Copied CD   else Original
  805.         cd.result[2] = 0x00;
  806.         cd.result[3] = 0;
  807.         *(UINT32 *)(cd.result + 4) = SCExID;
  808.  
  809.         cd.resultsize = 8;
  810.         cd.stat = 2;
  811.         break;
  812. /*
  813.     case CdlReadS:
  814.         cd.Status |= StatStandby;
  815.         SRESULT;
  816.         cd.stat = 2;
  817.         break;
  818. */
  819.     default:
  820.         printf("unknown cd command %d - %xh\n",data,data);
  821.         cd.stat = 2;
  822.     }
  823.  
  824.     PRINTRESULT
  825. //    VSync_Register = 0;
  826.     cd.resultptr = 0;
  827.     cd.resultready = 1;
  828.  
  829. /* cd_interrupt happen */
  830.     Irq_Pulse |= (1<<INT_CD);
  831. }
  832.  
  833. void dma3_exec(UINT32 adr,UINT32 bcr,UINT32 chcr)
  834. {
  835.     int size;
  836.  
  837. #if CON_OUTPUT
  838.     printf("cdma called: %08x %08x %08x\n",(int)adr,(int)bcr,(int)chcr);
  839. #endif
  840.  
  841. // get the size in bytes
  842.     size = (bcr>>16)*(bcr&0xffff)*4;
  843.     if (!size) size = bcr*4;
  844.  
  845.     CompileFlush(adr,adr+size);
  846.  
  847. // check the dma_chcr
  848.     switch(chcr) {
  849.     case 0x11000000:
  850.         if (cd.SectorBuf != NULL)
  851.         {
  852.             switch (cd.moderead) {
  853.             case 2:
  854.                 memcpy(RAMADDR(adr),SectorBuf,size);
  855.                 cd.SectorSize = 2048;
  856.                 cd.SectorBuf += 12;
  857.                 cd.moderead = 0;
  858.                 break;
  859.             case 1:
  860.             case 0:
  861.                 memcpy(RAMADDR(adr),cd.SectorBuf,size);
  862.                 cd.SectorBuf += size;
  863.                 if ((cd.SectorSize-=size) <= 0)
  864.                     cd.ctrl &= ~0x40;
  865.                 break;
  866.             }
  867. /*
  868.  
  869.             if (size <= 12) memcpy(RAMADDR(adr),cd.SectorBuf,size);
  870.             else {
  871.                 memcpy(RAMADDR(adr),SectorBuf+12,size);
  872.                 cd.ctrl &= ~0x40;
  873.             }
  874. */
  875.         } else {
  876.             memset(RAMADDR(adr),0,size);
  877.             cd.ctrl &= ~0x40;
  878.         }
  879.  
  880.         break;
  881.     }
  882. }